package org.hawk.gwtppc.webtest.tests.constructorsuite;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;

import org.hawk.gwtppc.webtest.common.Asserts;
import org.hawk.gwtppc.webtest.common.Test;
import org.hawk.gwtppc.webtest.tests.mock.ClassMock;
import org.hawk.gwtppc.webtest.tests.mock.EnumMock;
import org.hawk.gwtppc.webtest.tests.mock.GenericClassMock;
import org.hawk.gwtppc.webtest.tests.mock.SubClassMock1;
import org.hawk.gwtppc.webtest.tests.mock.SubClassMock2;

public class NewInstanceTest implements Test {

	public void run() throws Throwable {
		try {
			Constructor<EnumMock> c = EnumMock.class.getDeclaredConstructor(String.class,int.class);
			c.setAccessible(true);
			c.newInstance("", 0);
			Asserts.fail("Enum is not instantiable");
		} catch (IllegalArgumentException ex) {
		}
		try {
			ClassMock.class.getDeclaredConstructor().newInstance();
			Asserts.fail("Abstract class is not instantiable");
		} catch (InstantiationException ex) {
		}
		SubClassMock1 m1 = SubClassMock1.class.getDeclaredConstructor().newInstance();
		Asserts.assertFalse(m1 == null);
		Asserts.assertTrue(m1.getClass().equals(SubClassMock1.class));
		try {
			SubClassMock2.class.getDeclaredConstructor(String.class).newInstance("");
			Asserts.fail("Catched exception");
		} catch (InvocationTargetException ex) {
			Asserts.assertTrue(ex.getCause() instanceof AssertionError);
		}

		Constructor<SubClassMock2> c = SubClassMock2.class.getDeclaredConstructor(boolean.class);
		try {
			c.newInstance(false);
			Asserts.fail("Constructor is not accessible");
		} catch (IllegalAccessException ex) {
		}

		c.setAccessible(true);
		try {
			c.newInstance("");
			Asserts.fail("Bad argument type");
		} catch (IllegalArgumentException ex) {
		}

		SubClassMock2 m2 = c.newInstance(false);
		Asserts.assertFalse(m2 == null);
		Asserts.assertTrue(m2.getClass().equals(SubClassMock2.class));

		@SuppressWarnings("rawtypes")
		Constructor<GenericClassMock> c2 = GenericClassMock.class.getDeclaredConstructor(List.class, CharSequence.class, Object.class, Object.class);
		c2.setAccessible(true);
		
		@SuppressWarnings("rawtypes")
		GenericClassMock m3 = c2.newInstance(new ArrayList<Integer>(), null, new Object(), new Object());
		Asserts.assertFalse(m3 == null);
		Asserts.assertTrue(m3.getClass().equals(GenericClassMock.class));
	}

	public String getName() {
		return "newInstance(Object...)";
	}

}
